use std::{fs};

use fill_encrypt::{Encrypt, CustomResponse};
use reqwest::{multipart, Body, Client};
use tokio::fs::File;
use tokio_util::codec::{FramedRead, BytesCodec};

#[tauri::command]
pub fn zip(
    source_path: String,
    target_file: String
) -> Result<CustomResponse, String> {
    let result = Encrypt::zip(source_path, target_file)?;
    Ok(result)
}

#[tauri::command]
pub fn unzip(
    source_file: String,
    target_path: String
) -> Result<CustomResponse, String> {
    let result = Encrypt::unzip(source_file, target_path);

    Ok(match result {
        Ok(result) => result,
        Err(_) => CustomResponse {
            value: "fail".to_string()
        },
    })
}

#[tauri::command]
pub fn encrypt_content(content: String) -> Result<CustomResponse, String> {
    let result = Encrypt::encrypt_content(&content)?;
    Ok(result)
}

#[tauri::command]
pub fn decrypt_content(content: String) -> Result<CustomResponse, String> {
    let result = Encrypt::decrypt_content(&content)?;
    Ok(result)
}

#[tauri::command]
pub fn encrypt_file(
    source_file: String,
    target_file: String
) -> Result<(), String> {
    let _ =Encrypt::mix_file(&source_file, &target_file, true);
    Ok(())
}

#[tauri::command]
pub fn decrypt_file(
    source_file: String,
    target_file: String
) -> Result<(), String> {
    let _ = Encrypt::mix_file(&source_file, &target_file, false);
    Ok(())
}

#[tauri::command]
pub async fn upload_file(remote: String, target_file: String) -> Result<CustomResponse, String> {
    let file = fs::read(target_file).unwrap();
    let file_part = multipart::Part::bytes(file).mime_str("application/zip").unwrap();
    let form = reqwest::multipart::Form::new().part("file", file_part);
    let client = reqwest::Client::new();
    let result = client
        .post(remote.clone())
        .multipart(form)
        .send()
        .await;

    println!("{}", remote.clone().to_string());

    Ok(match result {
        Ok(result) => {
            println!("结果 {:?}", result);
            return Ok(CustomResponse { value: "success".to_string() })
        },
        Err(_) => CustomResponse {
            value: "fail".to_string()
        },
    })
}

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct Welcome {
    pub success: bool,
    pub message: String,
    pub show: bool,
    pub code: i64,
    pub data: Data,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Data {
    pub id: String,
    #[serde(rename = "fileName")]
    pub file_name: String,
    #[serde(rename = "newName")]
    pub new_name: String,
    #[serde(rename = "unitId")]
    pub unit_id: String,
    #[serde(rename = "unitName")]
    pub unit_name: String,
    #[serde(rename = "serverIp")]
    pub server_ip: String,
    #[serde(rename = "serverLocation")]
    pub server_location: String,
    #[serde(rename = "createTime")]
    pub create_time: String,
    pub origin: String,
    pub status: String,
}

#[tauri::command]
pub async fn reqwest_multipart_form(remote:&str, target_file: &str, file_name: &str) -> Result<CustomResponse, String> {
    let client = Client::new();

    //路径和 cargo.toml 在一个目录下面
    let file = File::open(target_file.clone().to_string()).await.unwrap();
    let file_body = file_to_body(file);
    println!("{}", target_file.clone().to_string());
    let bio = multipart::Part::stream(file_body).file_name(file_name.to_string()).mime_str("application/zip").unwrap();

    let form = multipart::Form::new()
        .part("file", bio);

    let response = client.post(remote).multipart(form).send().await;
    // let print_string = response.clone().text().await.unwrap();
    // println!("{:?}",print_string   );
    // let result = response.json::<Welcome>().await;
    // let result = HttpBinResult { args: None, data:None, files:None, form:None, headers: None, json: None, origin: None, url: None };

    Ok(
        match response {
            Ok(response) => {
                println!("{:?}", response);
                let result = response.json::<Welcome>().await;

                match result {
                    Ok(_result) => {
                        CustomResponse { value: "success".to_string() }
                    },
                    Err(_err) => {
                        CustomResponse { value: "fail".to_string() }
                    }
                }
            },
            Err(err) => {
                println!("{:?}", err.to_string());
                CustomResponse { value: "fail".to_string() }
            }
        }
    )
}

fn file_to_body(file: File) -> Body {
    let stream = FramedRead::new(file, BytesCodec::new());
    let body = Body::wrap_stream(stream);
    body
}
